﻿using Dyao.Book.Contract;

namespace Dyao.Book.Application
{
    /// <summary>
    /// 任务中心分布式任务更新上下文
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    public class TaskCenterDistributedContenxt<TResult> : TaskCenterExtend, ITaskCenterContext
    {
        private Func<Action<TaskCenterUpdatingResultModel<TResult>>, Task> _onUpdate;
        private Func<Task<string>> _getParams;

        public TaskCenterDistributedContenxt(TaskCenterDto taskModel, IServiceProvider serviceProvider)
        {
            TaskModel = taskModel;
            ServiceProvider = serviceProvider;
        }

        public IServiceProvider ServiceProvider { get; }

        public TaskCenterDto TaskModel { get; protected set; }

        public Func<TaskCenterDistributedCheckContext<TResult>, bool> CompleteChecker { get; set; }

        public Task UpdateAsync(Action<TaskCenterUpdatingResultModel<TResult>> action)
        {
            return _onUpdate(action);
        }

        public void SetOnUpdate(Func<Action<TaskCenterUpdatingResultModel<TResult>>, Task> func)
        {
            _onUpdate = func;
        }

        public Task<string> GetRequestParametersStringAsync()
        {
            return _getParams();
        }

        public void SetLoadRequestParams(Func<Task<string>> func)
        {
            _getParams = func;
        }
    }

    /// <summary>
    /// 任务中心分布式任务更新上下文
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    /// <typeparam name="TExecutingInfo"></typeparam>
    public class TaskCenterDistributedContenxt<TResult, TExecutingInfo> : TaskCenterExtend, ITaskCenterContext
    {
        private Func<Action<TaskCenterUpdatingInfoModel<TResult, TExecutingInfo>>, Task> _onUpdate;
        private Func<Task<string>> _getParams;

        public TaskCenterDistributedContenxt(TaskCenterDto taskModel, IServiceProvider serviceProvider)
        {
            TaskModel = taskModel;
            ServiceProvider = serviceProvider;
        }

        public IServiceProvider ServiceProvider { get; }

        public TaskCenterDto TaskModel { get; protected set; }

        public Func<TaskCenterDistributedCheckContext<TResult, TExecutingInfo>, bool> CompleteChecker { get; set; }

        public Task UpdateAsync(Action<TaskCenterUpdatingInfoModel<TResult, TExecutingInfo>> action)
        {
            return _onUpdate(action);
        }

        public void SetOnUpdate(Func<Action<TaskCenterUpdatingInfoModel<TResult, TExecutingInfo>>, Task> func)
        {
            _onUpdate = func;
        }

        public Task<string> GetRequestParametersStringAsync()
        {
            return _getParams();
        }

        public void SetLoadRequestParams(Func<Task<string>> func)
        {
            _getParams = func;
        }
    }

    public class TaskCenterUpdatingProgressModel
    {
        /// <summary>
        /// 执行进度
        /// </summary>
        public decimal Progress { get; set; }

        /// <summary>
        /// 任务执行结果提示消息
        /// </summary>
        public string ResultMessage { get; set; }

        /// <summary>
        /// 计算百分比
        /// </summary>
        /// <param name="currentCount">当前数量</param>
        /// <param name="totalCount">总数</param>
        /// <returns></returns>
        public decimal CalcPercentage(int currentCount, int totalCount)
        {
            if (currentCount >= totalCount) return 100m;

            return Math.Round(currentCount * 1m / totalCount, 2) * 100;
        }

        /// <summary>
        /// 增加进度
        /// </summary>
        /// <param name="progress"></param>
        public void AddProgress(decimal progress)
        {
            if (progress > 0)
            {
                this.Progress += progress;
            }
        }
    }

    public class TaskCenterUpdatingResultModel<TResult> : TaskCenterUpdatingProgressModel
    {
        /// <summary>
        /// 运行结果
        /// </summary>
        public TResult Result { get; set; }
    }

    public class TaskCenterUpdatingInfoModel<TResult, TExecutingInfo> : TaskCenterUpdatingResultModel<TResult>
    {
        public TaskCenterUpdatingInfoModel(TExecutingInfo info)
        {
            Info = info;
        }

        public TExecutingInfo Info { get; }
    }

    public class TaskCenterDistributedCheckContext
    {
    }

    public class TaskCenterDistributedCheckContext<TResult> : TaskCenterDistributedCheckContext
    {
        public TaskCenterDistributedCheckContext(TResult result)
        {
            Result = result;
        }

        public TResult Result { get; }
    }

    public class TaskCenterDistributedCheckContext<TResult, TExecutingInfo> : TaskCenterDistributedCheckContext<TResult>
    {
        public TaskCenterDistributedCheckContext(TExecutingInfo info, TResult result)
            : base(result)
        {
            Info = info;
        }

        public TExecutingInfo Info { get; }
    }
}
